Skip to content

fix(app): ask for one name when alerting a new saved search - #3563

Merged
kodiakhq[bot] merged 2 commits into
mainfrom
cursor/simplify-alert-name-fields-e389
Nov 5, 2026
Merged

kodiakhq[bot] merged 2 commits into
mainfrom
cursor/simplify-alert-name-fields-e389

Conversation

@MikeShi42

Copy link
Copy Markdown
Contributor

Summary

Creating an alert from the search page asked for two names and never said which was which.

On an unsaved search the modal showed a bordered "Saved search name" input in its header and the alert's own "Name" field, whose placeholder read "Defaults to the saved search or dashboard tile name" — a name field explaining itself in terms of a name field four pixels above it. On a saved search the header already read "Alerts for Checkout errors" and the alert's Name field was pre-filled with "Checkout errors" again, which reads as a duplicate rather than an override.

This is a prototype of the simplification: one name per screen.

  • Unsaved search: the search is named once, inline in the header, in the same InlineNameInput ("Untitled search") the saved search page uses for the same object. The alert's own name and tags row is gone — the create payload omits displayName/tags, which the server already derives from the saved search it is attached to, so the alert comes out named after the search either way. The tags button next to the name now tags the search (previously it tagged only the alert and the new search was silently saved untagged).
  • Saved search: the alert's field is labelled "Alert name" and left empty with the inherited name as its placeholder, so it reads as an override rather than a copy. Tags show "Inherited".
  • The unnamed-search error moved from a red toast to an inline message under the name, and now fires on the first submit alongside the other field errors rather than only after the webhook is valid.
  • The single "New Alert" tab is hidden when there is no saved search (nothing to switch between), and the modal's buttons are sentence case.

No API change. Removing the client-side prefill relies on deriveAlertDisplayFields, which already clamps the name and tags to the alert caps — the same clamping the client was doing by hand with clampAlertDisplayName/clampAlertTags.

Screenshots or video

Both captured on yarn dev, same viewport and theme.

Alerting an unsaved search — two name fields before, one after:

Before After
Before: Alerts for [Saved search name] input, plus a Name field placeholdered After: Alerts for [Untitled search] inline name and a tags button, with the helper line

Alerting a saved search — pre-filled duplicate before, inherited placeholder after:

Before After
Before: header After: header

Unnamed search on the first submit:

The inline name input outlined in red with

The alert created this way lands with the search's name and tags:

Alerts page listing an alert named

How to reproduce

Starting point: yarn dev (the Alerts button is hidden in local mode, so the demo server and the Vercel preview can't reach this modal). Register, then open Search and pick any logs source.

On main:

  1. Without saving the search, click Alerts.
  2. Two name inputs: "Saved search name" beside "Alerts for" in the header, and "Name" directly below it. Nothing says which one names what, or that leaving the second empty inherits the first.
  3. Click Save, name the search Checkout errors, then click Alerts again: the header says "Alerts for Checkout errors" and the Name field repeats Checkout errors.

On this branch:

  1. Without saving the search, click Alerts. One name, inline after "Alerts for", placeholdered "Untitled search", with "Saving creates this search; the alert takes its name and tags." underneath.
  2. Click Save search and alert with the name empty: "Name the search before saving it." appears inline, in the same pass as the webhook error.
  3. Type Payment failures, add the tag payments with the button beside the name, pick a webhook, and save. You land on the new saved search, and Alerts lists an alert named Payment failures tagged payments.
  4. On that saved search, click Alerts again: the field is now "Alert name", empty, placeholdered Payment failures, with tags reading "Inherited".

How to test on Vercel preview

N/A — the Alerts button is not rendered in local mode (IS_LOCAL_MODE), so the preview build cannot reach this modal.

References

  • Linear Issue: HDX-5917
Open in Web Open in Cursor 

Fixes HDX-5917

Creating an alert from the search page showed two name fields: a
"Saved search name" input in the modal header and the alert's own
"Name" field, with no way to tell which named what.

An unsaved search is now named once, inline in the header where the
saved search page names it, and the alert inherits that name and the
tags entered alongside it (the server already derives both when the
create payload omits them). On a saved search the alert's field is
labelled "Alert name" and shows the inherited name as a placeholder
instead of pre-filling a copy of it.
@MikeShi42
MikeShi42 requested a review from a team as a code owner November 4, 2026 21:41
@MikeShi42
MikeShi42 requested a review from karl-power November 4, 2026 21:41
@vercel

vercel Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
hyperdx-oss Ready Ready Preview Nov 5, 2026 2:22pm UTC
hyperdx-storybook Ready Ready Preview Nov 5, 2026 2:22pm UTC

Request Review

@changeset-bot

changeset-bot Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 15ee1bf

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@hyperdx/app Patch
@hyperdx/api Patch
@hyperdx/otel-collector Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added the review/tier-3 Standard — full human review required label Nov 4, 2026
@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

🟡 Tier 3 — Standard

Introduces new logic, modifies core functionality, or touches areas with non-trivial risk.

Why this tier:

  • Diff size: 261 production lines changed (Tier 2 max: < 250)

Review process: Full human review — logic, architecture, edge cases.
SLA: First-pass feedback within 1 business day.

Stats
  • Production files changed: 2
  • Production lines changed: 261 (+ 137 in test files, excluded from tier calculation)
  • Branch: cursor/simplify-alert-name-fields-e389
  • Author: MikeShi42

To override this classification, remove the review/tier-3 label and apply a different review/tier-* label. Manual overrides are preserved on subsequent pushes.

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Duplicate code analysis

No new duplicate code introduced by this PR.


jscpd compared this branch against origin/main
across app, api and common-utils. Only new clones are listed; the codebase
currently holds 114 in total (1.37%).
Run yarn dupes locally to reproduce, or yarn dupes:all for the full picture.

</Tags>
</Group>
{nameError ? (
<Text size="xs" c="red" data-testid="saved-search-name-error">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 minor — New validation text uses the raw palette color c="red" instead of the semantic Text variant

Use <Text size="xs" variant="danger" …>. The Repository conventions section 'Semantic component variants' says inline validation text should use variant="danger", not c="red".

Advisory. Fix if it is a small defect in code this PR changes; otherwise reply in the thread. Do not widen the PR or touch files it did not already change. How to respond

data-testid="saved-search-name-input"
/>
<Tags allowCreate values={tags} onChange={onTagsChange}>
<Button

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 minor — Tags button has no accessible name: screen readers announce only the count ("0")

Add something like aria-label={Saved search tags (${tags.length})} to the Button. Its only content is the decorative IconTags and a number, so nothing tells a screen-reader user what the control does.

Advisory. Fix if it is a small defect in code this PR changes; otherwise reply in the thread. Do not widen the PR or touch files it did not already change. How to respond

@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

PR Review

If you are a coding agent acting for the author, read this first.
Nothing below blocks merge automatically; a maintainer decides. What they will expect:

  • 🔴 critical or 🟠 major in code this PR adds or changes: fix before asking for review.
  • 🔵 minor in code this PR changes: your call. Fix if small, otherwise reply.
  • Anything about surrounding code, or asking you to widen the change (hoist a helper,
    dedupe with another file, fix other call sites): never fix here, whatever the
    severity. Reply with one sentence; if it is critical, say so plainly so a human sees it.

One commit per review round. After two rounds, stop and ask a maintainer to review
scope rather than addressing more automated findings. Full rule: AGENTS.md.

5 finding(s): 🔴 0 critical · 🟠 0 major · 🔵 5 minor

2 posted as inline comment(s) on the changed lines. 3 listed below.

Findings outside the changed lines

3 minor
  • 🔵 packages/app/src/__tests__/DBSearchPageAlertModal.test.tsx:585 — New search-tags behaviour is never tested; the test only checks the empty default tags: [] → Pick a tag through saved-search-tags-button and assert that createSavedSearchMutateAsync receives it. If tags: newSavedSearchTags were reverted to tags: [], the current test would still pass, even though this is the fix the PR describes.
  • 🔵 packages/app/src/__tests__/DBSearchPageAlertModal.test.tsx:612 — First-submit test never checks that the alert-field errors appear in the same pass → Also assert that the webhook validation error renders alongside saved-search-name-error. That pins down the reason onSubmitAttempt exists. Right now the test would pass even if the name were only validated inside onSubmit, which is the toast-era ordering the PR claims to fix.
  • 🔵 packages/app/src/DBSearchPageAlertModal.tsx:234 — Leaving the name empty saves a copy, so editing the alert later shows the duplicate name again → When displayName/tags are omitted, the server saves the derived values (alert.displayName ?? derivedDisplay.displayName, packages/api/src/controllers/alerts.ts:278-279). So on the 'Alert N' edit tab, 'Alert name' comes back pre-filled with the search name and tags no longer show 'Inherited'. Either persist null on create so the value is resolved when read (resolveAlertDisplayFields), or blank the field in edit mode when it equals the derived name.

Severity is the reviewer's own estimate and is used for ordering, not filtering. No finding blocks merge automatically; a maintainer decides.

@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Deep Review

✅ No critical issues found. The diff is a clean, well-tested UI refactor: the two schemas it relies on are .nullish() (so omitting displayName/tags validates), and the server (deriveAlertDisplayFields) clamps both the derived name and tags, so removing the client-side prefill/clamp is safe. The P2 items below are pre-existing reliability gaps sitting in the flow this PR reworks, plus one missing test for genuinely new behavior.

🟡 P2 — recommended

  • packages/app/src/DBSearchPageAlertModal.tsx:729 — The submit button's loading prop omits createSavedSearch.isPending, so during the first mutation of the new-search flow the button stays enabled and a second click re-enters onSubmit, creating duplicate saved searches and alerts (pre-existing, but inside the reworked flow).
    • Fix: Add createSavedSearch.isPending to the loading prop so the button is disabled while the saved search is being created.
    • ce-correctness-reviewer, ce-julik-frontend-races-reviewer, ce-adversarial-reviewer
  • packages/app/src/DBSearchPageAlertModal.tsx:573 — When createAlert rejects after createSavedSearch resolves, the saved search is already persisted but the user sees only a generic error and the modal closes, leaving an orphaned search with no alert (pre-existing).
    • Fix: On createAlert failure keep the modal open and either roll back the created saved search or navigate to it so a retry targets only the alert.
    • ce-adversarial-reviewer, ce-julik-frontend-races-reviewer, ce-correctness-reviewer
  • packages/app/src/__tests__/DBSearchPageAlertModal.test.tsx:294 — The new tags-on-new-search capability is untested; the unsaved-search test only asserts the default tags: [], so reverting the newSavedSearchTags wiring to a hardcoded empty list would still pass.
    • Fix: Add a test that adds a tag via saved-search-tags-button, submits, and asserts createSavedSearch is called with the tag in tags.
    • ce-testing-reviewer, ce-kieran-typescript-reviewer, ce-adversarial-reviewer
🔵 P3 nitpicks (6)
  • packages/app/src/DBSearchPageAlertModal.tsx:559 — New-search state is split across newSavedSearchForm (name) and a separate newSavedSearchTags useState, giving one logical entity two sources of truth read back independently at submit.
    • Fix: Fold tags into the form as a Controller-driven field, or add a comment explaining why they deliberately live outside it.
    • ce-kieran-typescript-reviewer, ce-maintainability-reviewer
  • packages/app/src/DBSearchPageAlertModal.tsx:723 — Name validation is split across the onSubmitAttempt pre-trigger and an awaited trigger() in onSubmit, a keep-in-sync coupling across two forms that is not cross-referenced.
    • Fix: Cross-reference the two trigger sites in a comment, or consolidate the parent-owned fields into a single validate-then-submit pass.
    • ce-kieran-typescript-reviewer, ce-maintainability-reviewer
  • packages/app/src/DBSearchPageAlertModal.tsx:628 — On the new-search success path onClose() runs twice (inside the branch after router.push and again after the try/catch), and the trailing onClose() also fires on error; harmless today but inconsistent (pre-existing).
    • Fix: Close and invalidate only in the success branch and return early from the catch.
    • ce-julik-frontend-races-reviewer, ce-correctness-reviewer
  • packages/app/src/__tests__/DBSearchPageAlertModal.test.tsx:271 — No test asserts the alert tabs are absent for an unsaved search, though the whole Tabs block is newly gated behind id.
    • Fix: In the unsaved-search test assert screen.queryByRole('tab') is not in the document.
  • packages/app/src/DBSearchPageAlertModal.tsx:440 — The header's new savedSearch?.where ?? searchedConfig?.where fallback is unasserted in either branch.
    • Fix: Assert the unsaved-search header renders searchedConfig.where.
  • packages/app/src/components/AlertDisplayFields.tsx:49 — The new displayNameLabel="Alert name" override is unverified; the saved-search test checks only the inherited placeholder, not the label.
    • Fix: Assert the label reads Alert name in the saved-search test.

Reviewers (6): ce-correctness-reviewer, ce-kieran-typescript-reviewer, ce-julik-frontend-races-reviewer, ce-testing-reviewer, ce-maintainability-reviewer, ce-adversarial-reviewer.

Testing gaps:

  • No test for the double-submit race (rapid second click must not create a second saved search/alert).
  • No test for createSavedSearch succeeding then createAlert rejecting (orphaned search + modal-closes-on-error).
  • No test that the inline name error clears after a valid name is typed following a failed first submit.
  • Refuted and not reported: stale new-search state on reopen (the modal unmounts via isAlertModalOpen && and a successful create navigates away) and whitespace-only names (the validate rule and the submit both trim()).

No finding blocks merge automatically. A maintainer will expect P0/P1 findings in code this PR changes to be fixed; P2/P3 are your call -- fix or reply. Never fix findings about surrounding code here; reply instead. Do not widen the PR. How to respond

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

E2E Test Results

✅ All tests passed • 463 passed • 1 skipped • 1822s

Status Count
✅ Passed 463
❌ Failed 0
⚠️ Flaky 1
⏭️ Skipped 1

Tests ran across 4 shards in parallel.

View full report →

@kodiakhq
kodiakhq Bot merged commit ec0db7a into main Nov 5, 2026
28 checks passed
@kodiakhq
kodiakhq Bot deleted the cursor/simplify-alert-name-fields-e389 branch November 5, 2026 14:29

This branch was successfully deployed

2 active deployments
Preview – hyperdx-oss — 15ee1bf9 Deployed Nov 5, 2026 by vercel[bot]
Preview – hyperdx-storybook — 15ee1bf9 Deployed Nov 5, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automerge review/tier-3 Standard — full human review required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants